package cc.verywell.pureblock.msg.nfs.idx.extraUpload;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cc.verywell.pureblock.func.node.KeyShell;
import cc.verywell.pureblock.msg.nfs.idx.NfsidxStructure;
import cc.verywell.pureblock.net.NormalSession;

/**
* 
* Copyright © 2019 TanYaqiu. All rights reserved.
* @author TanYaqiu 
* @address flat 601
* @date 2019年10月2日 下午9:18:28
*/
public class UploadingWatch implements UploadSupply {
	final public KeyShell key;
	final public HashMap<UploadingMonitor,NfsidxStructure> monitor;
	private boolean disAble = false;
	public int storeCount;
	public long storeTime;
	public int wantCount;
	public long wantTime;

	public UploadingWatch(KeyShell key) {
		monitor = new HashMap<>(1);
		this.key = key;
	}
	
	public void addMonitor(UploadingMonitor m,NfsidxStructure idx) {
		boolean isAdd = false;
		synchronized (monitor) {
			isAdd = null==monitor.putIfAbsent(m,idx);
		}
		if(isAdd)m.addbyWatch(this);
	}
	NfsidxStructure removeMonitorByMonitor(UploadingMonitor m) {
		synchronized (monitor) {
			NfsidxStructure idx = monitor.remove(m);
			if(idx instanceof ErrNfsidxStructure)return null;
			return idx;
		}
	}
	
	///外部同步块内处理
	boolean needDisable() {
		if(monitor.isEmpty()) {
			disAble = true;
			return true;
		}else {
			return false;
		}
	}
	boolean disabled() {
		return disAble;
	}
	///外部同步块内处理
	
	
	@Override
	public void fireStoreFile(NormalSession nc, List<byte[]> fileHash) {
		storeCount++;
		storeTime = System.currentTimeMillis();
		UploadingMonitor[] fires;
		synchronized (monitor) {
			fires = monitor.keySet().toArray(new UploadingMonitor[monitor.size()]);
		}
		for (UploadingMonitor m : fires) {
			m.fireStateUpdate(this);
		}
		
	}
	@Override
	public void fireWantFile(NormalSession nc, byte[] fileHash) {
		wantCount++;
		wantTime = System.currentTimeMillis();
		UploadingMonitor[] fires;
		synchronized (monitor) {
			fires = monitor.keySet().toArray(new UploadingMonitor[monitor.size()]);
		}
		for (UploadingMonitor m : fires) {
			m.fireStateUpdate(this);
		}
	}
	
	@Override
	public NfsidxStructure needNewExternalFile(KeyShell key, NfsidxStructure errFile) {
		HashMap<UploadingMonitor,NfsidxStructure> fires = null;
		synchronized (monitor) {
			NfsidxStructure newFile = null;
			for (Map.Entry<UploadingMonitor,NfsidxStructure> m : monitor.entrySet()) {
				if(m.getValue() instanceof ErrNfsidxStructure) {
				}else if(m.getValue().equals(errFile)) {
					m.setValue(new ErrNfsidxStructure(m.getValue()));
				}else if(newFile==null) {
					newFile = m.getValue();
				}
			}
			if(newFile!=null)return newFile;
			fires = new HashMap<UploadingMonitor,NfsidxStructure>(monitor);
		}
		for (Map.Entry<UploadingMonitor,NfsidxStructure> m : fires.entrySet()) {
			m.getKey().fireNoMoreIdx(this.key, m.getValue());
		}
		return null;
	}
	
	@Override
	public int hashCode() {
		return key.hashCode();
	}
	
	private class ErrNfsidxStructure extends NfsidxStructure{
		public ErrNfsidxStructure(NfsidxStructure old) {
			super(old);
		}
	}

}
